package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumTrackListVo;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfo(Long trackId) {
        //  先获取声音对象
        TrackInfo trackInfo = this.getById(trackId);
        //  track_info;
        this.removeById(trackId);
        //  track_stat;
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
        //  album_info; include_track_count-1;
        AlbumInfo albumInfo = this.albumInfoMapper.selectById(trackInfo.getAlbumId());
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        this.albumInfoMapper.updateById(albumInfo);
        //  维护track_info.order_num 字段！
        //  update track_info set order_num = order_num - 1 where album_id = 1 and order_num > 50 and is_deleted = 0
        trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
        //  vod 如果说云点播删除失败！重试机制！
        try {
            vodService.removeMediaByFileId(trackInfo.getMediaFileId());
        } catch (Exception e) {
            //  sendMsg(); 重试！
            throw new RuntimeException(e);
        }
    }

    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> trackListVoPage, Long albumId, Long userId) {
        /*
        1.  获取到当前专辑对应的声音列表;  50条;  专辑的类型：免费  【vip免费 付费 除了试听集数外，都应该付费】
        2.  判断当前用户是否购买过声音或专辑！
         */
        IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectAlbumTrackPage(trackListVoPage, albumId);
        //  根据专辑Id获取专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //  判断用户是否登录!
        if (null == userId) {
            //  未登录！ 判断专辑类型;
            String payType = albumInfo.getPayType();
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(payType)) {
                //  vip免费 或 付费 除了试听集数外，都应该付费！
                //  获取免费的试听集数
                Integer tracksForFree = albumInfo.getTracksForFree();
                //                for (AlbumTrackListVo albumTrackListVo : pageInfo.getRecords()) {
                //                    if (albumTrackListVo.getOrderNum() > tracksForFree) {
                //                        //  设置为付费
                //                        albumTrackListVo.setIsShowPaidMark(true);
                //                    }
                //                }
                pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree).forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
            }
        } else {
            //  专辑： 免费，付费，vip免费
            //  用户登录    获取用户信息
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
            //  判断
            Assert.notNull(userInfoVoResult, "用户信息不存在");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            //  判断
            Assert.notNull(userInfoVo, "用户信息不存在");
            //  声明一个付费标识;
            boolean isPaid = false;
            //  判断专辑类型为vip免费：
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                //  用户是否是vip - 不属于vip 或 是vip但已过期；需要收费
                if (userInfoVo.getIsVip() == 0 || userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date())) {
                    isPaid = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                //  需要付费;
                isPaid = true;
            }
            //  统一处理付费情况
            if (isPaid) {
                //  需要付费！
                //  1.  免费试听集数有多少集； 2.  用户是否购买过专辑(userId,albumId)user_paid_album，或购买过声音 user_paid_track！
                Integer tracksForFree = albumInfo.getTracksForFree();
                //  albumId = 1466  25条声音；5条免费； 付费20条； 判断用户是否够买过 20 条中的某一条声音！
                List<AlbumTrackListVo> albumTrackListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree).collect(Collectors.toList());
                List<Long> isNeedPaidTrackIdList = albumTrackListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                //  远程调用用户微服务的方法；
                Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, isNeedPaidTrackIdList);
                Assert.notNull(mapResult, "用户购买信息不存在");
                //  trackId:1 trackId:0 1：表示购买过 0：未购买  isShowPaidMark=true或fasle;
                Map<Long, Integer> map = mapResult.getData();
                for (AlbumTrackListVo albumTrackListVo : albumTrackListVoList) {
                    //  map.get(albumTrackListVo.getTrackId()) == 1?albumTrackListVo.setIsShowPaidMark(false):albumTrackListVo.setIsShowPaidMark(true);
                    //  boolean flag = map.get(albumTrackListVo.getTrackId()) == 1?false:true; // 购买过；
                    boolean flag = map.get(albumTrackListVo.getTrackId()) == 1 ? false : true; // 购买过；
                    albumTrackListVo.setIsShowPaidMark(flag);
                }
            }
        }
        //  返回数据
        return pageInfo;
    }

    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        //  修改 track_info;
        /*
        1.  trackInfoVo 有修改的数据;
        2.  修改的本质就是执行 update 语句;
        3.  修改声音： vod , track_info 流媒体的字段;
        4.
         */
        TrackInfo trackInfo = this.getById(trackId);
        //  获取到原有的声音Id
        String mediaFileId = trackInfo.getMediaFileId();
        //  属性拷贝
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        if (!mediaFileId.equals(trackInfoVo.getMediaFileId())) {
            //  说明修改了！ 删除云点播原有的声音
            vodService.removeMediaByFileId(mediaFileId);
            //  获取到新的流媒体的相关数据
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            trackInfo.setMediaDuration(mediaInfo.getDuration());
            trackInfo.setMediaFileId(trackInfoVo.getMediaFileId());
            trackInfo.setMediaSize(mediaInfo.getSize());
            trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
        }
        //  更新声音
        trackInfoMapper.updateById(trackInfo);

    }

    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
        //  调用服务层方法
        return trackInfoMapper.selectUserTrackPage(trackListVoPage, trackInfoQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        //	track_info
        TrackInfo trackInfo = new TrackInfo();
        //	给声音对象赋值
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //	拷贝之后将没有赋值的数据赋值
        trackInfo.setUserId(userId);
        //	order_num 是什么? include_track_count + 1;
        //	先获取到专辑对象;
        AlbumInfo albumInfo = this.albumInfoMapper.selectById(trackInfo.getAlbumId());
        trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
        //	给流媒体数据赋值： 通过声音Id查找声音数据; 只能通过vod-api查询
        TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        if (null != trackMediaInfoVo) {
            trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());
            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
            trackInfo.setMediaType(trackMediaInfoVo.getType());
        }
        trackInfoMapper.insert(trackInfo);
        //	album_info include_track_count--包含声音总数
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        this.albumInfoMapper.updateById(albumInfo);
        //	track_stat
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);


    }

    public void saveTrackStat(Long trackId, String trackType) {
        //  保存数据
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(trackId);
        trackStat.setStatType(trackType);
        trackStat.setStatNum(new Random().nextInt(10000));
        this.trackStatMapper.insert(trackStat);

    }
}
